home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: selectDisk.c,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:40 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
- #include "mutex_compile.h"
-
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "thread.h"
- #include "semaphore.h"
- #include "latch.h"
- #include "link.h"
- #include "host.h"
- #include "bitvec.h"
- #include "bf.h"
- #include "disk.h"
- #include "volume.h"
- #include "pool.h"
- #include "threadstate.h"
- #include "msgvector.h"
- #include "msg_funcs.h"
- #include "thread_funcs.h"
- #include "disk_funcs.h"
- #include "mr_extfuncs.h"
- #include "thread_globals.h"
- #include "msg_globals.h"
- #include "recover_globals.h"
- #include "io_globals.h"
- #include "sm_params.h"
- #include "queue_globals.h"
- #include "stat_globals.h"
- #include "queue_consist.h"
- #include "sm_params.h"
-
- /*
- * selectDisk() is a bit of a misnomer, since no select() system
- * call is done. This routine just checks all the disk
- * queues to see if any are ready to deliver results to the
- * server process. If not, the select() system call in loop()
- * will wait to be kicked by the disk processes. This
- * routine simply allows the two processes to avoid some
- * unnecessary socket activity.
- */
-
-
- /*
- * First priority:
- * If there are any completed requests, process them (don't return).
- * 2nd priority:
- * If any threads are waiting to write to a disk and the
- * disk can now accommodate them, move the thread to the
- * ready list (move only the first such thread for each disk).
- * Return 1 if any threads found, 0 if not.
- */
-
- int
- selectDisk ()
-
- {
- #ifdef JUNK
- static TIMEVAL Poll = { 0,0 };
- #endif JUNK
- static int lastFromQChecked= 0,
- lastToQChecked= 0;
- register int j,last, found=0, failed=0;
- register QUEUEPAIR *qp;
- register VOLREC *volRec;
-
- TRPRINT(TR_DISK, TR_LEVEL_3,
- ("select disk, lastTo %d, lastFrom %d",lastToQChecked,
- lastFromQChecked));
-
- /*
- * Replies->willBlock means that the consumer of the replies (server
- * process) will do a select before it checks the queues again.
- * When it's false, the server will check the queues before doing
- * its next select. It's not precise; it's slightly pessimistic,
- * as you can see: we're about to check the queues right now.
- * But that's ok, since being kicked unnecessarily by a disk process
- * to get us out of a select is not an error; it's just an
- * inefficiency. We hope that 99% of the time, this semaphore
- * will prevent unnecessary kicks.
- */
- Replies->willBlock = 1;
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1, ("Server willBlock"));
-
- checkAll:
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1, ("checking fromDisk Qs"));
- last = lastFromQChecked;
- for(j=last+1, lastFromQChecked=j%NumVolumes;
- (disk_requests_out>0) && (j<=(last+NumVolumes));
- lastFromQChecked = (++j)%NumVolumes) {
-
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1,
- ("checking fromDisk #%d", lastFromQChecked));
- qp = diskQueue(lastFromQChecked);
- volRec = qp->volRec;
- SM_ASSERT( LEVEL_1, (volRec != NULL) );
- SM_ASSERT(LEVEL_1, (volRec->queues == qp));
- if( volRec->diskrwPid == 0 ) /* not mounted */
- continue;
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1,
- ("checking from Q disk %d", lastFromQChecked));
-
- SM_ASSERT(LEVEL_3, (qp!=NULL));
-
- /*
- * we mustn't block here, so we only try once for the turn
- */
- if(tryMutex(&(qp->fromDisk.mutex))) {
- disk_replies_found++;
- diskReceiveQ(qp, TRUE /* holding mutex */);
- /* if we return, there wasn't anything to receive.
- * and, btw, we gave up the mutex
- */
- disk_replies_found--;
- } else {
- failed++;
- }
- }
- if(failed) {
- /*
- * If we get here, we didn't get any work from any of the
- * disk queues. The reason is one of two: either
- * none of the disks had anything to give us, or
- * some disk process was using its queue so we failed
- * to get mutex on that queue with the tryMutex() call above.
- * In the latter case we want to run through the whole loop again.
- */
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1, ("failed: check again"));
- goto checkAll;
- }
- /*
- * If we get here, there's truly
- * nothing to read from disk so now let's see if anything is
- * waiting to write to the disk.
- * We move to the ready queue the first process from *each*
- * disk queue wait list.
- */
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1,
- ("Checking To Qs, lastTo %d, lastFrom %d",lastToQChecked,
- lastFromQChecked));
-
- last = lastToQChecked;
-
- for(j=last+1, lastToQChecked=j%NumVolumes;
- (threads_awaiting_q>0) && (j<=(last+NumVolumes));
- lastToQChecked = (++j)%NumVolumes) {
- TCB *tcb;
-
- volRec = diskQueue(lastToQChecked)->volRec;
-
- if( (volRec->volflags & VOL_OPEN)==0 )
- continue;
-
- TRPRINT(TR_DISK|TR_DISKRW, TR_LEVEL_1, ("checking To Q disk %d",
- lastToQChecked));
-
- #define diskTakingRequests tcbList
- if(LIST_EMPTY( &(volRec->diskTakingRequests))) {
- /*
- * noone waiting on this disk
- */
- continue;
- }
-
- qp = diskQueue(lastToQChecked);
- SM_ASSERT(LEVEL_3, qp);
-
- /*
- * we mustn't block here, so we only try once for the turn
- */
- if(!tryMutex(&(qp->toDisk.mutex))) {
- /* couldn't inspect queue -- skip to next volume */
- continue;
- }
- if(toDiskFull(qp)) {
- /* try next volume */
- giveMutex(&(qp->toDisk.mutex));
- continue;
- }
- giveMutex(&(qp->toDisk.mutex));
- found++;
- tcb = (TCB *) listDeq( &(volRec->diskTakingRequests) );
- threads_awaiting_q--;
- SM_ASSERT(LEVEL_1, tcb != NULL);
-
- CHECK_TCB_MAGIC(tcb);
-
- /*
- * check to see that the thread is in wait
- * with state == "waiting for disk q to shrink"
- */
- SM_ASSERT(LEVEL_3, tcb->state == THREAD_DISK_Q_WAIT);
-
- /*
- * put the thread on the ready queue
- */
- TRPRINT(TR_DISK, TR_LEVEL_1,
- ("putting tcb %d on ready list", (tcb-Tcbs)));
- listEnq( &ReadyList, &(tcb->controlList) );
-
- TRPRINT(TR_DISK, TR_LEVEL_3, ("process moved", lastToQChecked));
-
- }
-
- TRPRINT(TR_DISK, TR_LEVEL_1,
- ("select disk found %s", found?"something":"nothing"));
- return found;
- }
-